﻿using CLM.Gestao.Administrador.BLL;
using CLM.Gestao.Administrador.DAL;
using CLM.Gestao.Custos.BLL;
using CLM.Gestao.Despesas.BLL;
using CLM.Gestao.Importacao;
using CLM.Gestao.Vendas.BLL;
using System;
using System.Collections.Generic;
using System.Linq;

namespace CLM.Gestao.Rateios.BLL
{
    public class Lancamento : LancamentoBLO<TB_LANCAMENTO>
    {
        #region Propriedades

        public int IdLancamento { get; set; }
        public int IdCentroCusto { get; set; }
        public int IdContaContabil { get; set; }
        public int IdLancamentoTipo { get; set; }
        public int IdProjeto { get; set; }
        public DateTime DataLancamento { get; set; }
        public decimal ValorLancamento { get; set; }
        public DateTime DataEntradaSun { get; set; }
        public int IdPeriodo { get; set; }
        public DateTime DataInclusao { get; set; }
        public string DescricaoLancamento { get; set; }
        public int IdEvento { get; set; }
        public int IdFuncionario { get; set; }
        public int IdMapaEstrategicoItem { get; set; }
        public bool IndicaDespesaComprometida { get; set; }
        public string ContratoDespesaComprometida { get; set; }

        #endregion Propriedades

        #region Conversões

        private List<TB_LANCAMENTO> ConvertToEDM(List<Lista> pLista)
        {
            List<TB_LANCAMENTO> List = (from l in pLista
                                        select new TB_LANCAMENTO
                                        {
                                            CONTRATO_DESPESA_COMPROMETIDA = l.ContratoDespesaComprometida,
                                            DATA_ENTRADA_SUN = DateTime.Parse(l.DataEntradaSun.ToString()),
                                            DATA_INCLUSAO = DateTime.Parse(l.DataInclusao.ToString()),
                                            DATA_LANCAMENTO = DateTime.Parse(l.DataLancamento.ToString()),
                                            DESCRICAO_LANCAMENTO = l.DescricaoLancamento.Trim(),
                                            ID_CENTRO_CUSTO = int.Parse(l.IdCentroCusto.ToString()),
                                            ID_CONTA_CONTABIL = int.Parse(l.IdContaContabil.ToString()),
                                            ID_EVENTO = int.Parse(l.IdEvento.ToString()),
                                            ID_FUNCIONARIO = int.Parse(l.IdFuncionario.ToString()),
                                            ID_LANCAMENTO_TIPO = int.Parse(l.IdLancamentoTipo.ToString()),
                                            ID_LANCAMENTO = int.Parse(l.IdLancamento.ToString()),
                                            ID_MAPA_ESTRATEGICO_ITEM = int.Parse(l.IdMapaEstrategicoItem.ToString()),
                                            ID_PERIODO = int.Parse(l.IdPeriodo.ToString()),
                                            ID_PROJETO = int.Parse(l.IdProjeto.ToString()),
                                            INDICA_DESPESA_COMPROMETIDA = bool.Parse(l.IndicaDespesaComprometida.ToString()),
                                            VALOR_LANCAMENTO = decimal.Parse(l.ValorLancamento.ToString()),

                                        }).ToList();
            return List;
        }

        private List<Lista> ConvertToContext(IQueryable<TB_LANCAMENTO> pContext)
        {
            List<Lista> List = (from l in pContext
                                select new Lista
                                {
                                    ContratoDespesaComprometida = l.CONTRATO_DESPESA_COMPROMETIDA,
                                    CodigoContaContabil = l.TB_CONTA_CONTABIL.CODIGO_CONTA_CONTABIL.Trim(),
                                    DescricaoContaContabil = l.TB_CONTA_CONTABIL.DESCRICAO_CONTA_CONTABIL.Trim(),
                                    CategoriaCentroCusto = l.TB_CENTRO_CUSTO.TB_CATEGORIA_CENTRO_CUSTO.NOME_CATEGORIA_CENTRO_CUSTO.Trim(),
                                    NomeCentroCusto = l.TB_CENTRO_CUSTO.NOME_CENTRO_CUSTO.Trim(),
                                    CodigoCentroCusto = l.TB_CENTRO_CUSTO.CODIGO_CENTRO_CUSTO.Trim(),
                                    IndicaGerencial = l.TB_CENTRO_CUSTO.INDICA_GERENCIAL,
                                    IndicaCorporativo = l.TB_CENTRO_CUSTO.INDICA_DESPESAS_CORPORATIVAS,
                                    IndicaAlocacao = l.TB_CENTRO_CUSTO.INDICA_ALOCACAO,
                                    DataEntradaSun = l.DATA_ENTRADA_SUN,
                                    DataInclusao = l.DATA_INCLUSAO,
                                    DataLancamento = l.DATA_LANCAMENTO,
                                    DescricaoLancamento = l.DESCRICAO_LANCAMENTO.Trim(),
                                    IdCentroCusto = l.ID_CENTRO_CUSTO,
                                    IdContaContabil = l.ID_CONTA_CONTABIL,
                                    IdEvento = l.ID_EVENTO,
                                    IdFuncionario = l.ID_FUNCIONARIO,
                                    IdLancamentoTipo = l.ID_LANCAMENTO_TIPO,
                                    IdLancamento = l.ID_LANCAMENTO,
                                    IdMapaEstrategicoItem = l.ID_MAPA_ESTRATEGICO_ITEM,
                                    IdPeriodo = l.ID_PERIODO,
                                    IdProjeto = l.ID_PROJETO,
                                    IndicaDespesaComprometida = l.INDICA_DESPESA_COMPROMETIDA,
                                    ValorLancamento = l.VALOR_LANCAMENTO,
                                    IdLancamentoDespesa = l.TB_LANCAMENTO_DESPESA.Select(x => x.ID_LANCAMENTO_DESPESA).FirstOrDefault(),
                                    IdIndicadorDespesa = l.TB_LANCAMENTO_DESPESA.Select(x => x.ID_INDICADOR_DESPESA).FirstOrDefault(),
                                    DescricaoLancamentoTipo = l.TB_LANCAMENTO_TIPO.DESCRICAO_LANCAMENTO_TIPO,
                                    IdProdutoVenda = l.TB_LANCAMENTO_VENDA.Select(x => x.ID_PRODUTO).FirstOrDefault()
                                }).ToList();
            return List;
        }

        #endregion Conversões

        #region CRUD

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pLista"></param>
        public void Add(List<Lista> pLista)
        {
            try
            {
                foreach (var item in ConvertToEDM(pLista))
                    base.Add(item);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pLista"></param>
        public void Delete(List<Lista> pLista)
        {
            try
            {
                foreach (var item in ConvertToEDM(pLista))
                    base.Delete(item);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pLista"></param>
        public void Update(List<Lista> pLista)
        {
            try
            {
                foreach (var item in ConvertToEDM(pLista))
                    base.Update(item);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// Efetua a pesquisa na tabela, filtrando as solicitações do usuário
        /// </summary>
        /// <param name="pPesquisa">pPesquisa</param>
        /// <returns>Lista</returns>
        private IQueryable<TB_LANCAMENTO> Get(Lista pPesquisa)
        {
            IQueryable<TB_LANCAMENTO> Consulta;

            Consulta = from p in GetAll()
                       select p;
            if (pPesquisa != null)
            {
                if (!string.IsNullOrWhiteSpace(pPesquisa.IdIndicadorDespesa.ToString()) && pPesquisa.IdIndicadorDespesa != 0)
                    Consulta = from p in Consulta.SelectMany(s => s.TB_LANCAMENTO_DESPESA.Where(wr => wr.ID_INDICADOR_DESPESA == pPesquisa.IdIndicadorDespesa))
                               select p.TB_LANCAMENTO;

                if (pPesquisa.IndicaGerencial != null)
                    Consulta = from p in Consulta
                               where p.TB_CENTRO_CUSTO.INDICA_GERENCIAL == pPesquisa.IndicaGerencial
                               select p;

                if (pPesquisa.DataLancamento != null)
                    Consulta = from p in Consulta
                               where p.DATA_LANCAMENTO == pPesquisa.DataLancamento
                               select p;

                if (pPesquisa.IndicaCorporativo != null)
                    Consulta = from p in Consulta
                               where p.TB_CENTRO_CUSTO.INDICA_DESPESAS_CORPORATIVAS == pPesquisa.IndicaCorporativo
                               select p;

                if (pPesquisa.IndicaAlocacao != null)
                    Consulta = from p in Consulta
                               where p.TB_CENTRO_CUSTO.INDICA_ALOCACAO == pPesquisa.IndicaAlocacao
                               select p;

                if (pPesquisa.DescricaoLancamentoTipo != null)
                    Consulta = from p in Consulta
                               where p.TB_LANCAMENTO_TIPO.DESCRICAO_LANCAMENTO_TIPO == pPesquisa.DescricaoLancamentoTipo
                               select p;

                if (pPesquisa.IdPeriodo != null)
                    Consulta = from p in Consulta
                               where p.ID_PERIODO == pPesquisa.IdPeriodo
                               select p;

                if (pPesquisa.IndicaIndicadorDespesa != null)
                    Consulta = from p in Consulta
                               where (p.TB_CENTRO_CUSTO.TB_CATEGORIA_CENTRO_CUSTO != null && p.TB_CENTRO_CUSTO.TB_CATEGORIA_CENTRO_CUSTO.ID_INDICADOR_DESPESA != null)
                               select p;

                if (pPesquisa.IndicaTradeAllowance != null)
                    Consulta = from p in Consulta
                               where (p.TB_CENTRO_CUSTO.INDICA_TRADE_ALLOWANCE != null)
                               select p;


                Consulta = from p in Consulta select p;
            }
            return Consulta;
        }
        private IQueryable<TB_LANCAMENTO> GetDespesas(Lista pPesquisa)
        {
            IQueryable<TB_LANCAMENTO> Consulta;

            Consulta = from p in GetAllDespesas()
                       select p;

            // Filtro para trazer os lançamentos para rateio
            Consulta = from p in Consulta
                       where p.TB_LANCAMENTO_TIPO.DESCRICAO_LANCAMENTO_TIPO == "Real"
                            || p.TB_LANCAMENTO_TIPO.DESCRICAO_LANCAMENTO_TIPO == "Alocação Real"
                            || p.TB_LANCAMENTO_TIPO.DESCRICAO_LANCAMENTO_TIPO == "Amostras de Invoices"
                            || p.TB_LANCAMENTO_TIPO.DESCRICAO_LANCAMENTO_TIPO == "Amostras de Ordem de Produção"
                            || p.TB_LANCAMENTO_TIPO.DESCRICAO_LANCAMENTO_TIPO == "Amostras de Vendas"
                            || p.TB_LANCAMENTO_TIPO.DESCRICAO_LANCAMENTO_TIPO == "Amostras de Compras"
                            || p.TB_LANCAMENTO_TIPO.DESCRICAO_LANCAMENTO_TIPO == "Ajuste Gerencial"
                       select p;


            if (pPesquisa != null)
            {
                if (!string.IsNullOrWhiteSpace(pPesquisa.IdIndicadorDespesa.ToString()) && pPesquisa.IdIndicadorDespesa != 0)
                    Consulta = from p in Consulta.SelectMany(s => s.TB_LANCAMENTO_DESPESA.Where(wr => wr.ID_INDICADOR_DESPESA == pPesquisa.IdIndicadorDespesa))
                               select p.TB_LANCAMENTO;

                if (pPesquisa.IndicaGerencial != null)
                    Consulta = from p in Consulta
                               where p.TB_CENTRO_CUSTO.INDICA_GERENCIAL == pPesquisa.IndicaGerencial
                               select p;

                if (pPesquisa.DataLancamento != null)
                    Consulta = from p in Consulta
                               where p.DATA_LANCAMENTO == pPesquisa.DataLancamento
                               select p;

                if (pPesquisa.IndicaCorporativo != null)
                    Consulta = from p in Consulta
                               where p.TB_CENTRO_CUSTO.INDICA_DESPESAS_CORPORATIVAS == pPesquisa.IndicaCorporativo
                               select p;

                if (pPesquisa.IndicaAlocacao != null)
                    Consulta = from p in Consulta
                               where p.TB_CENTRO_CUSTO.INDICA_ALOCACAO == pPesquisa.IndicaAlocacao
                               select p;

                //if (pPesquisa.DescricaoLancamentoTipo != null)
                //    Consulta = from p in Consulta
                //               where p.TB_LANCAMENTO_TIPO.DESCRICAO_LANCAMENTO_TIPO == pPesquisa.DescricaoLancamentoTipo
                //               select p;

                if (pPesquisa.IdPeriodo != null)
                    Consulta = from p in Consulta
                               where p.ID_PERIODO == pPesquisa.IdPeriodo
                               select p;

                if (pPesquisa.IndicaIndicadorDespesa != null)
                    Consulta = from p in Consulta
                               where (p.TB_CENTRO_CUSTO.TB_CATEGORIA_CENTRO_CUSTO != null && p.TB_CENTRO_CUSTO.TB_CATEGORIA_CENTRO_CUSTO.ID_INDICADOR_DESPESA != null)
                               select p;

                if (pPesquisa.IndicaTradeAllowance != null)
                    Consulta = from p in Consulta
                               where (p.TB_CENTRO_CUSTO.INDICA_TRADE_ALLOWANCE != null)
                               select p;


                Consulta = from p in Consulta select p;
            }
            return Consulta;
        }

        private IQueryable<TB_LANCAMENTO> GetVendas(Lista pPesquisa)
        {
            IQueryable<TB_LANCAMENTO> Consulta;

            Consulta = from p in GetAllVendas()
                       select p;

            // Filtro para trazer os lançamentos para rateio
            Consulta = from p in Consulta
                       where p.TB_LANCAMENTO_TIPO.DESCRICAO_LANCAMENTO_TIPO == "Real"
                            || p.TB_LANCAMENTO_TIPO.DESCRICAO_LANCAMENTO_TIPO == "Alocação Real"
                            || p.TB_LANCAMENTO_TIPO.DESCRICAO_LANCAMENTO_TIPO == "Amostras de Invoices"
                            || p.TB_LANCAMENTO_TIPO.DESCRICAO_LANCAMENTO_TIPO == "Amostras de Ordem de Produção"
                            || p.TB_LANCAMENTO_TIPO.DESCRICAO_LANCAMENTO_TIPO == "Amostras de Vendas"
                            || p.TB_LANCAMENTO_TIPO.DESCRICAO_LANCAMENTO_TIPO == "Amostras de Compras"
                            || p.TB_LANCAMENTO_TIPO.DESCRICAO_LANCAMENTO_TIPO == "Ajuste Gerencial"
                       select p;


            if (pPesquisa != null)
            {
                if (!string.IsNullOrWhiteSpace(pPesquisa.IdIndicadorDespesa.ToString()) && pPesquisa.IdIndicadorDespesa != 0)
                    Consulta = from p in Consulta.SelectMany(s => s.TB_LANCAMENTO_DESPESA.Where(wr => wr.ID_INDICADOR_DESPESA == pPesquisa.IdIndicadorDespesa))
                               select p.TB_LANCAMENTO;

                if (pPesquisa.IndicaGerencial != null)
                    Consulta = from p in Consulta
                               where p.TB_CENTRO_CUSTO.INDICA_GERENCIAL == pPesquisa.IndicaGerencial
                               select p;

                if (pPesquisa.DataLancamento != null)
                    Consulta = from p in Consulta
                               where p.DATA_LANCAMENTO == pPesquisa.DataLancamento
                               select p;

                if (pPesquisa.IndicaCorporativo != null)
                    Consulta = from p in Consulta
                               where p.TB_CENTRO_CUSTO.INDICA_DESPESAS_CORPORATIVAS == pPesquisa.IndicaCorporativo
                               select p;

                if (pPesquisa.IndicaAlocacao != null)
                    Consulta = from p in Consulta
                               where p.TB_CENTRO_CUSTO.INDICA_ALOCACAO == pPesquisa.IndicaAlocacao
                               select p;

                //if (pPesquisa.DescricaoLancamentoTipo != null)
                //    Consulta = from p in Consulta
                //               where p.TB_LANCAMENTO_TIPO.DESCRICAO_LANCAMENTO_TIPO == pPesquisa.DescricaoLancamentoTipo
                //               select p;

                if (pPesquisa.IdPeriodo != null)
                    Consulta = from p in Consulta
                               where p.ID_PERIODO == pPesquisa.IdPeriodo
                               select p;

                if (pPesquisa.IndicaIndicadorDespesa != null)
                    Consulta = from p in Consulta
                               where (p.TB_CENTRO_CUSTO.TB_CATEGORIA_CENTRO_CUSTO != null && p.TB_CENTRO_CUSTO.TB_CATEGORIA_CENTRO_CUSTO.ID_INDICADOR_DESPESA != null)
                               select p;

                if (pPesquisa.IndicaTradeAllowance != null)
                    Consulta = from p in Consulta
                               where (p.TB_CENTRO_CUSTO.INDICA_TRADE_ALLOWANCE != null)
                               select p;


                Consulta = from p in Consulta select p;
            }
            return Consulta;
        }

        #endregion CRUD

        #region Retorna Listas e Itens

        public List<Lista> GetLista()
        {
            return GetLista(new Lista());
        }

        public List<Lista> GetLista(Lista pPesquisa)
        {
            var ListaLancamento = ConvertToContext(Get(pPesquisa));
            return ListaLancamento;
        }
        public List<Lista> GetListaDespesas(Lista pPesquisa)
        {
            var ListaLancamento = ConvertToContext(GetDespesas(pPesquisa));
            return ListaLancamento;
        }

        public List<Lista> GetListaVendas(Lista pPesquisa)
        {
            var ListaLancamento = ConvertToContext(GetVendas(pPesquisa));
            return ListaLancamento;
        }

        #endregion Retorna Listas e Itens

        #region Consultas


        #endregion Consultas

        #region Processos

        #region Alocações

        public void ValidarCalculoAlocacao(int pIdPeriodo)
        {
            LancamentoTipo tipo = new LancamentoTipo();
            int iIdLanctoTipoReal = tipo.GetId("Real");

            CentroCusto centro = new CentroCusto();

            var Centros = (from s in centro.GetAll()
                           where s.INDICA_ALOCACAO == true
                           select new CentroCusto.Lista
                           {
                               IdCentroCusto = s.ID_CENTRO_CUSTO
                           }).ToList();

            if (Centros.Count < 0)
                throw new Exception("Nenhum centro de custo está marcado como centro de custo para alocação.");


            int qtd = (from s in GetAll()
                       where s.TB_CENTRO_CUSTO.INDICA_DESPESAS_CORPORATIVAS == true && s.ID_PERIODO == pIdPeriodo && s.ID_LANCAMENTO_TIPO == iIdLanctoTipoReal
                       select s).ToList().Count() * Centros.Count();

            if (qtd == 0)
                throw new Exception("Nenhum lançamento encontrado para alocação.");
        }

        public void ExcluirAlocacoesAnteriores(int pIdPeriodo)
        {
            LancamentoTipo tipo = new LancamentoTipo();

            int iIdLanctoTipoAlocacao = tipo.GetId("Alocação Real");
            LancamentoDespesa despesas = new LancamentoDespesa();
            var lancamentos = (from s in GetLista(new Lista() { DescricaoLancamentoTipo = "Alocação Real", IdPeriodo = pIdPeriodo })
                               join d in despesas.GetLista()
                               on s.IdLancamento equals d.IdLancamento
                               select new TB_LANCAMENTO_DESPESA
                               {
                                   ID_LANCAMENTO_DESPESA = d.IdLancamentoDespesa,
                                   TB_LANCAMENTO = new TB_LANCAMENTO()
                                   {
                                       ID_LANCAMENTO = s.IdLancamento
                                   }
                               }).ToList();

            int i = 0;
            foreach (var item in lancamentos)
            {
                TB_LANCAMENTO l = item.TB_LANCAMENTO;
                despesas.Delete(item);
                Delete(l);

                i++;
                OnImportData(this, new ImportDataEventArgs("Excluindo...", i, lancamentos.Count()));
            }
        }

        public void CalcularAlocacao(int pIdPeriodo)
        {

            LancamentoTipo tipo = new LancamentoTipo();

            int iIdLanctoTipoAlocacao = tipo.GetId("Alocação Real");

            int iIdLanctoTipoReal = tipo.GetId("Real");

            CentroCusto centro = new CentroCusto();

            var Centros = (from s in centro.GetAll()
                           where s.INDICA_ALOCACAO == true
                           select new CentroCusto.Lista
                           {
                               IdCentroCusto = s.ID_CENTRO_CUSTO
                           }).ToList();

            int qtdCentros = Centros.Count();

            int qtd = (from s in GetAll()
                       where s.TB_CENTRO_CUSTO.INDICA_DESPESAS_CORPORATIVAS == true && s.ID_PERIODO == pIdPeriodo && s.ID_LANCAMENTO_TIPO == iIdLanctoTipoReal
                       select s).ToList().Count() * Centros.Count();

            int i = 0;

            foreach (var item in Centros)
            {
                List<Lista> Valores = (from s in GetAll()
                                       where s.TB_CENTRO_CUSTO.INDICA_DESPESAS_CORPORATIVAS == true && s.ID_PERIODO == pIdPeriodo && s.ID_LANCAMENTO_TIPO == iIdLanctoTipoReal
                                       select new Lista
                                       {
                                           IdLancamentoTipo = s.ID_LANCAMENTO_TIPO,
                                           IdCentroCusto = item.IdCentroCusto,
                                           IdCentroCustoGerencial = s.ID_CENTRO_CUSTO,
                                           ValorLancamento = s.VALOR_LANCAMENTO / qtdCentros,
                                           DescricaoLancamento = s.DESCRICAO_LANCAMENTO,
                                           IdContaContabil = s.ID_CONTA_CONTABIL,
                                           IdProjeto = s.ID_PROJETO,
                                           IdPeriodo = s.ID_PERIODO

                                       }).ToList();


                foreach (var l in Valores)
                {
                    Add(new TB_LANCAMENTO()
                    {
                        ID_LANCAMENTO_TIPO = iIdLanctoTipoAlocacao,
                        ID_CENTRO_CUSTO = l.IdCentroCusto,
                        VALOR_LANCAMENTO = l.ValorLancamento,
                        DATA_LANCAMENTO = System.DateTime.Now,
                        DESCRICAO_LANCAMENTO = "Alocação - " + l.DescricaoLancamento,
                        ID_CONTA_CONTABIL = l.IdContaContabil,
                        ID_PROJETO = l.IdProjeto,
                        ID_PERIODO = l.IdPeriodo,
                        TB_LANCAMENTO_DESPESA = new TrackableCollection<TB_LANCAMENTO_DESPESA>() {
                            new TB_LANCAMENTO_DESPESA()
                            {
                                ID_INDICADOR_DESPESA = 1
                             }
                        }
                    });

                    Add(new TB_LANCAMENTO()
                    {
                        ID_LANCAMENTO_TIPO = iIdLanctoTipoAlocacao,
                        ID_CENTRO_CUSTO = l.IdCentroCustoGerencial,
                        VALOR_LANCAMENTO = l.ValorLancamento * (-1),
                        DATA_LANCAMENTO = System.DateTime.Now,
                        DESCRICAO_LANCAMENTO = "Alocação - " + l.DescricaoLancamento,
                        ID_CONTA_CONTABIL = l.IdContaContabil,
                        ID_PROJETO = l.IdProjeto,
                        ID_PERIODO = l.IdPeriodo,
                        TB_LANCAMENTO_DESPESA = new TrackableCollection<TB_LANCAMENTO_DESPESA>() {
                            new TB_LANCAMENTO_DESPESA()
                            {
                                ID_INDICADOR_DESPESA = 1
                             }
                        }
                    });


                    i++;
                    OnImportData(this, new ImportDataEventArgs("Incluindo valores de Alocação...", i, qtd));

                }
                Save();
            }

            OnImportData(this, new ImportDataEventArgs("Cálculo de Alocação efetuado com sucesso."));

        }

        #endregion Alocações

        #region Rateios

        public void ValidarCalculoRateio(int pIdPeriodo)
        {
            try
            {
                OnImportData(this, new ImportDataEventArgs("Validando dados para rateio (Lançamentos de Despesa)..."));
                // Verificar se existem lançamentos de despesa
                LancamentoDespesa despesa = new LancamentoDespesa();
                var lancamentos = (from s in GetListaDespesas(new Lista())
                                   select s.ValorLancamento).Sum();

                if (lancamentos == 0)
                    throw new Exception("Valores de despesa não encontrados para rateio.");

                lancamentos = null;
                despesa = null;

                OnImportData(this, new ImportDataEventArgs("Validando dados para rateio (Lançamentos de Venda)..."));
                // Verificar se existem lançamentos de vendas
                LancamentoVenda venda = new LancamentoVenda();
                lancamentos = (from s in GetListaVendas(new Lista())
                               select s.ValorLancamento).Sum();

                if (lancamentos == 0)
                    throw new Exception("Valores de venda não encontrados para rateio.");

                lancamentos = null;
                venda = null;

                OnImportData(this, new ImportDataEventArgs("Validando dados para rateio (Relacionamento de Produtos)..."));
                // verificar se os centros de custo estão relacionados com os produtos
                CentroCustoProdutoAtivo cCustoProduto = new CentroCustoProdutoAtivo();
                var centros = (from s in cCustoProduto.GetLista()
                               select s.IdCentroCusto).Count();

                if (centros == 0)
                    throw new Exception("Não existem produtos relacionados com os centros de custo.");

                cCustoProduto = null;

                OnImportData(this, new ImportDataEventArgs("Validando dados para rateio (Parâmetros de Rateio)..."));
                // Verificar se os centros de custo possuem tipo de driver de rateio
                CentroCustoDriverRateioTipo driver = new CentroCustoDriverRateioTipo();
                centros = (from s in driver.GetLista()
                           select s.IdCentroCusto).Count();

                if (centros == 0)
                    throw new Exception("Não existem tipos de driver de rateio relacionados com os centros de custo.");

                driver = null;

                OnImportData(this, new ImportDataEventArgs("Validando dados para rateio (Drivers de Rateio)..."));
                // verificar se os produtos possuem driver ggf
                ProdutoDriverRateioValor produtoDriver = new ProdutoDriverRateioValor();
                var produtos = (from s in produtoDriver.GetLista()
                                where (s.ValorGGF != null) && (s.IdPeriodo == pIdPeriodo)
                                select s.IdProduto).Count();

                if (produtos == 0)
                    throw new Exception("Valores de driver GGF não encontrados para o período informado.");

                produtoDriver = null;
            }
            catch (Exception ex)
            {
                Exportacao.Texto.LogErro(ex, "Validando dados para rateio");
                throw new Exception(ex.Message);
            }
        }

        public void ExcluirRateiosAnteriores(int pIdPeriodo)
        {
            try
            {
                // Dictionary de Indicadores de Custos para recuperar o ID, utilizando o nome
                IndicadorCusto IndicadorCusto = new IndicadorCusto();
                var IndicadoresCustos = IndicadorCusto.GetLista().ToDictionary(d => d.NomeIndicadorCusto.ToUpper());

                // Dictionary de Indicadores de Despesas para recuperar o ID, utilizando o nome
                IndicadorDespesa IndicadorDespesa = new IndicadorDespesa();
                var IndicadoresDespesas = IndicadorDespesa.GetLista().ToDictionary(d => d.NomeIndicadorDespesa);

                // Dictionary de Indicadores de Vendas para recuperar o ID, utilizando o nome
                IndicadorVenda IndicadorVenda = new IndicadorVenda();
                var IndicadoresVendas = IndicadorVenda.GetLista().ToDictionary(d => d.NomeIndicadorVenda);

                OnImportData(this, new ImportDataEventArgs("Excluindo rateios anteriores..."));

                SPExcluirRateiosAnterioresCustos ExcluirRateiosAnterioresCustos = new SPExcluirRateiosAnterioresCustos();
                ExcluirRateiosAnterioresCustos.Execute(pIdPeriodo, (int)IndicadoresCustos[Indicadores.IndicadoresCustos.OtherCostsUndefined.ToUpper()].IdIndicadorCusto);
                ExcluirRateiosAnterioresCustos = null;

                //SPExcluirRateiosAnterioresDespesas ExcluirRateiosAnterioresDespesas = new SPExcluirRateiosAnterioresDespesas();
                ////OBS: o segundo parâmetro vai fixo como 1, mas é desconsiderado na PROC
                ////     Esta medida foi adotada para não precisar refazer o EDM após a edição da PROC
                //ExcluirRateiosAnterioresDespesas.Execute(pIdPeriodo, 1);
                //ExcluirRateiosAnterioresDespesas = null;

                //SPExcluirRateiosAnterioresVendas ExcluirRateiosAnterioresVendas = new SPExcluirRateiosAnterioresVendas();
                //ExcluirRateiosAnterioresVendas.Execute(pIdPeriodo, (int)IndicadoresVendas[Indicadores.IndicadoresVendas.TradeAllowances].IdIndicadorVenda, (int)IndicadoresVendas[Indicadores.IndicadoresVendas.NetNetSales].IdIndicadorVenda);
                //ExcluirRateiosAnterioresVendas = null;

                //// Excluir valores anteriores de Indicadores Net Net Sales
                //SPExcluirIndicadoresNetNet ExcluirIndicadores = new SPExcluirIndicadoresNetNet();
                //ExcluirIndicadores.Execute(pIdPeriodo);
                //ExcluirIndicadores = null;

                IndicadorCusto = null;
                IndicadoresCustos = null;
                IndicadorDespesa = null;
                IndicadoresDespesas = null;
                IndicadorVenda = null;
                IndicadoresVendas = null;
            }
            catch (Exception ex)
            {
                Exportacao.Texto.LogErro(ex, "Excluindo rateios anteriores");
                throw new Exception(ex.Message);
            }

            #region Excluir

            //// Trade Allowance e Net Net Sales
            //// Busca os valores de venda pelo período informado
            //LancamentoVenda LancamentoVenda = new LancamentoVenda();
            //var Lancamentos = (from s in GetLista(new Lista() { IdPeriodo = pIdPeriodo })
            //                   //where s.DescricaoLancamentoTipo != "Real"
            //                   join d in LancamentoVenda.GetLista()
            //                   on s.IdLancamento equals d.IdLancamento
            //                   where (d.IdIndicadorVenda == IndicadoresVendas["Trade Allowances"].IdIndicadorVenda || d.IdIndicadorVenda == IndicadoresVendas["Net Net Sales"].IdIndicadorVenda)
            //                   select new TB_LANCAMENTO_VENDA
            //                   {
            //                       ID_LANCAMENTO_VENDA = d.IdLancamentoVenda,
            //                       TB_LANCAMENTO = new TB_LANCAMENTO()
            //                       {
            //                           ID_LANCAMENTO = s.IdLancamento
            //                       }
            //                   }).ToList();

            //int i = 0;
            //foreach (var item in Lancamentos)
            //{
            //    TB_LANCAMENTO l = item.TB_LANCAMENTO;
            //    LancamentoVenda.Delete(item);
            //    Delete(l);

            //    i++;
            //    OnImportData(this, new ImportDataEventArgs("Excluindo...", i, Lancamentos.Count()));
            //}
            //LancamentoVenda.Save();
            //Save();

            //// Busca os valores de venda pelo período informado
            //LancamentoCusto Custos = new LancamentoCusto();
            //var LancamentosC = (from s in GetLista(new Lista() { IdPeriodo = pIdPeriodo, DescricaoLancamentoTipo = "Rateio GGF Real" })
            //                    join d in Custos.GetLista()
            //                    on s.IdLancamento equals d.IdLancamento
            //                    where (d.IdIndicadorCusto == IndicadoresCustos["GGF"].IdIndicadorCusto)
            //                    select new TB_LANCAMENTO_CUSTO
            //                    {
            //                        ID_LANCAMENTO_CUSTO = d.IdLancamentoCusto,
            //                        TB_LANCAMENTO = new TB_LANCAMENTO()
            //                        {
            //                            ID_LANCAMENTO = s.IdLancamento
            //                        }
            //                    }).ToList();

            //i = 0;
            //foreach (var item in LancamentosC)
            //{
            //    TB_LANCAMENTO l = item.TB_LANCAMENTO;
            //    Custos.Delete(item);
            //    Delete(l);

            //    i++;
            //    OnImportData(this, new ImportDataEventArgs("Excluindo...", i, LancamentosC.Count()));
            //}
            //Custos.Save();
            //Save();

            //// Busca os valores de venda pelo período informado
            //LancamentoDespesa LancamentoDespesa = new LancamentoDespesa();
            //var LancamentosD = (from s in GetLista(new Lista() { IdPeriodo = pIdPeriodo, DescricaoLancamentoTipo = "Rateio Vendas Real" })
            //                    join d in LancamentoDespesa.GetLista()
            //                    on s.IdLancamento equals d.IdLancamento
            //                    where (d.IdIndicadorDespesa == IndicadoresDespesas["Vendas"].IdIndicadorDespesa)
            //                    select new TB_LANCAMENTO_DESPESA
            //                    {
            //                        ID_LANCAMENTO_DESPESA = d.IdLancamentoDespesa,
            //                        TB_LANCAMENTO = new TB_LANCAMENTO()
            //                        {
            //                            ID_LANCAMENTO = s.IdLancamento
            //                        }
            //                    }).ToList();

            //i = 0;
            //foreach (var item in LancamentosD)
            //{
            //    TB_LANCAMENTO l = item.TB_LANCAMENTO;
            //    LancamentoDespesa.Delete(item);
            //    Delete(l);

            //    i++;
            //    OnImportData(this, new ImportDataEventArgs("Excluindo...", i, LancamentosD.Count()));
            //}
            //LancamentoDespesa.Save();
            //Save();

            #endregion Excluir
        }

        public void CalcularRateios(int pIdPeriodo, int pIdPeriodoAno, int pMes, int pAno)
        {
            GC.Collect();
            GC.AddMemoryPressure(Int32.MaxValue);

            LancamentoTipo LancamentoTipo = new LancamentoTipo();

            int idLancamentoTipoRateioGGF = LancamentoTipo.GetId("Rateio GGF Real");
            int idLancamentoTipoRateioVendas = LancamentoTipo.GetId("Rateio Vendas Real");
            int idLancamentoTipoRateioTradeAllowance = LancamentoTipo.GetId("Rateio TradeAllowance Real");

            // Dictionary de Contas Contábeis para recuperar o ID, utilizando a descrição
            ContaContabil ContaContabil = new ContaContabil();
            var ContasContabeis = ContaContabil.GetItens(new ContaContabil.Lista() { IndicaGerencial = true }).ToDictionary(d => d.CodigoContaContabil + d.DescricaoContaContabil.ToUpper());
            ContaContabil = null;

            // Dictionary de Indicadores de Vendas para recuperar o ID, utilizando o nome
            IndicadorVenda IndicadorVendas = new IndicadorVenda();
            var IndicadoresVendas = IndicadorVendas.GetLista().ToDictionary(d => d.NomeIndicadorVenda);
            IndicadorVendas = null;

            // Dictionary de Indicadores de Custos para recuperar o ID, utilizando o nome
            IndicadorCusto indicadorCusto = new IndicadorCusto();
            var IndicadoresCustos = indicadorCusto.GetLista().ToDictionary(d => d.NomeIndicadorCusto);
            indicadorCusto = null;

            // Dictionary de Indicadores de Despesas para recuperar o ID, utilizando o nome
            IndicadorDespesa indicadorDespesa = new IndicadorDespesa();
            var IndicadoresDespesas = indicadorDespesa.GetLista().ToDictionary(d => d.NomeIndicadorDespesa);
            indicadorDespesa = null;

            // Dictionary de Indicadores de Despesas para recuperar o ID, utilizando o nome
            var LancamentosTipos = LancamentoTipo.GetLista().ToDictionary(d => d.DescricaoLancamentoTipo);

            DriverRateioTipo DriverRateioTipo = new DriverRateioTipo();
            var DriversRateiosTipos = DriverRateioTipo.GetLista().ToDictionary(d => d.NomeDriverRateioTipo);
            DriverRateioTipo = null;

            LancamentoDespesa lancamentoDespesa = new LancamentoDespesa();
            List<Lista> Valores = (from s in GetListaDespesas(new Lista() { IndicaIndicadorDespesa = true, IdPeriodo = pIdPeriodo })
                                   select s).ToList();

            CentroCustoDriverRateioTipo CentroCustoDriverRateioTipo = new CentroCustoDriverRateioTipo();
            List<CentroCustoDriverRateioTipo.Lista> TiposRateios = (from s in CentroCustoDriverRateioTipo.GetLista(new CentroCustoDriverRateioTipo.Lista { IdPeriodoAno = pIdPeriodoAno })
                                                                    select s).ToList();


            CentroCusto CentroCusto = new CentroCusto();
            List<CentroCusto.Lista> centros;
            int i;
            int contadorSaves;
            decimal? TotalDriverFamilia;
            List<Lista> Rateios = new List<Lista>();
            ProdutoDriverRateioValor pdrv = new ProdutoDriverRateioValor();

            ProdutoDriverRateioValor ProdutoDriverRateioValor = new ProdutoDriverRateioValor();
            List<ProdutoDriverRateioValor.Lista> ListaProdutoDriverRateioValor = (from s in ProdutoDriverRateioValor.GetLista(new ProdutoDriverRateioValor.Lista { IdPeriodo = pIdPeriodo })
                                                                                  select s).ToList();

            #region Coment1
            // #region Atualiza valores de drivers vendas
            //try
            //{
            //    AtualizaValorDriverVenda(pIdPeriodo);
            //}
            //catch (Exception ex)
            //{
            //    Exportacao.Texto.LogErro(ex, "Atualiza valores de drivers vendas");
            //    throw new Exception(ex.Message);
            //}


            //#endregion

            //GC.Collect();

            //#region Rateio Trade Allowances

            //try
            //{
            //    OnImportData(this, new ImportDataEventArgs("Calculando rateio de Trade Allowance..."));

            //    List<Lista> valoresTradeAllowance = (from s in GetLista(new Lista() { IdPeriodo = pIdPeriodo, DescricaoLancamentoTipo = "Real", IndicaTradeAllowance = true })
            //                                         join d in lancamentoDespesa.GetLista()
            //                                         on s.IdLancamento equals d.IdLancamento
            //                                         select s).ToList();

            //    centros = (from s in CentroCusto.GetLista(new CentroCusto.Lista() { IndicaTradeAllowance = true })
            //               select new CentroCusto.Lista
            //               {
            //                   IdCentroCusto = s.IdCentroCusto,
            //                   Produtos = CentroCusto.GetProdutos(s.IdCentroCusto, pIdPeriodo)
            //               }).ToList();

            //    LancamentoVenda LancamentoVenda = new LancamentoVenda();



            //    i = 0;
            //    foreach (var cent in centros)
            //    {
            //        i++;
            //        OnImportData(this, new ImportDataEventArgs("Calculando Rateio Trade Allowances...", i, centros.Count()));

            //        var totalDriver = (from s in ListaProdutoDriverRateioValor
            //                           join p in cent.Produtos
            //                           on s.IdProduto equals p.IdProduto
            //                           select s.ValorVenda).Sum();

            //        foreach (var prod in cent.Produtos)
            //        {

            //            Rateios = (from s in valoresTradeAllowance.Where(w => w.IdCentroCusto == cent.IdCentroCusto).Select(s => s)
            //                       select new Lista
            //                       {
            //                           IdCentroCusto = s.IdCentroCusto,
            //                           ValorLancamento = totalDriver == 0 ? 0 : s.ValorLancamento * ((prod.DriverVenda == null ? 0 : prod.DriverVenda) / totalDriver),
            //                           DescricaoLancamento = "Rateio Trade Allowance - " + s.DescricaoLancamento,
            //                           IdPeriodo = s.IdPeriodo,
            //                           DataLancamento = System.DateTime.Now,

            //                           IdContaContabil = ContasContabeis[("9899Trade Allowances").ToUpper()].IdContaContabil
            //                       }).ToList();

            //            foreach (var lanc in Rateios)
            //            {
            //                if (lanc.ValorLancamento != 0)
            //                {
            //                    Add(new TB_LANCAMENTO()
            //                    {
            //                        ID_CENTRO_CUSTO = lanc.IdCentroCusto,
            //                        VALOR_LANCAMENTO = Math.Round((decimal)(lanc.ValorLancamento == null ? 0 : lanc.ValorLancamento), 2),
            //                        DESCRICAO_LANCAMENTO = lanc.DescricaoLancamento,
            //                        ID_PERIODO = lanc.IdPeriodo,
            //                        DATA_LANCAMENTO = lanc.DataLancamento,
            //                        ID_CONTA_CONTABIL = lanc.IdContaContabil,
            //                        ID_LANCAMENTO_TIPO = LancamentosTipos["Real"].IdLancamentoTipo,
            //                        TB_LANCAMENTO_VENDA = new TrackableCollection<TB_LANCAMENTO_VENDA>()
            //                    {
            //                        new TB_LANCAMENTO_VENDA()
            //                        {
            //                             ID_INDICADOR_VENDA = IndicadoresVendas[Indicadores.IndicadoresVendas.TradeAllowances].IdIndicadorVenda,
            //                             ID_PRODUTO = prod.IdProduto,
            //                             INDICA_PROVISAO = false,
            //                             MERCADORIA = 0,
            //                             IPI = 0,
            //                             REPASSE = 0,
            //                             DESCONTO = 0,
            //                             TOTAL_NF = 0,
            //                             ICMS = 0,
            //                             ICMSST = 0,
            //                             PIS = 0,
            //                             COFINS = 0,
            //                             INSS = 0,
            //                             LIQUIDO = 0
            //                        }
            //                    }
            //                    });
            //                }
            //            }
            //            Save();
            //            LancamentoVenda.Save();
            //        }
            //    }
            //}
            //catch (Exception ex)
            //{
            //    Exportacao.Texto.LogErro(ex, "Rateio trade Allowance");
            //    throw new Exception(ex.Message);
            //}

            //#endregion Rateio Trade Allowances

            //GC.Collect();

            //#region Atualiza indicador Net Net Sales para vendas

            //try
            //{
            //    OnImportData(this, new ImportDataEventArgs("Atualizando indicadores Net Net Sales..."));
            //    AtualizaIndicadorNetNetSales(pIdPeriodo);
            //}
            //catch (Exception ex)
            //{
            //    Exportacao.Texto.LogErro(ex, "Atualiza indicador Net Net Sales para vendas");
            //    throw new Exception(ex.Message);
            //}


            //#endregion

            //GC.Collect();

            //#region Atualiza valores de drivers net net sales
            //try
            //{
            //    OnImportData(this, new ImportDataEventArgs("Atualizando valores de driver Net Net Sales..."));
            //    AtualizaValorDriverNetNet(pIdPeriodo);
            //}
            //catch (Exception ex)
            //{
            //    Exportacao.Texto.LogErro(ex, "Atualiza valores de drivers net net sales");
            //    throw new Exception(ex.Message);
            //}


            //#endregion

            ////GC.Collect();           
            #endregion



            #region Rateio GGF
            //try
            //{
            //    OnImportData(this, new ImportDataEventArgs("Cálculo de rateio GGF..."));
            //    CategoriaCentroCusto categoria = new CategoriaCentroCusto();
            //    var IdCategoriaHort = categoria.GetItens(new CategoriaCentroCusto.Lista() { NomeCategoriaCentroCusto = "Hort" }).First().IdCategoriaCentroCusto;
            //    categoria = null;

            //    centros = (from s in CentroCusto.GetLista(new CentroCusto.Lista() { IdCategoriaCentroCusto = IdCategoriaHort })
            //               select new CentroCusto.Lista
            //               {
            //                   IdCentroCusto = s.IdCentroCusto,
            //                   Produtos = CentroCusto.GetProdutos(s.IdCentroCusto, pIdPeriodo)
            //               }).ToList();


            //    List<Lista> ValoresDespGGF = (from s in GetListaDespesas(new Lista())
            //                                  select s).ToList();


            //    LancamentoCusto LancamentoCusto = new LancamentoCusto();
            //    LancamentoCustoHistorico lancHist = new LancamentoCustoHistorico();

            //    i = 0;
            //    contadorSaves = 0;

            //    foreach (var cent in centros)
            //    {
            //        i++;
            //        OnImportData(this, new ImportDataEventArgs("Calculando Rateio GGF...", i, centros.Count()));

            //        var totalDriver = (from s in ListaProdutoDriverRateioValor
            //                           join p in cent.Produtos
            //                           on s.IdProduto equals p.IdProduto
            //                           select s.ValorGGF).Sum();

            //        foreach (var prod in cent.Produtos)
            //        {

            //            Rateios = (from s in ValoresDespGGF.Where(w => w.IdCentroCusto == cent.IdCentroCusto).Select(s => s)
            //                       select new Lista
            //                       {
            //                           IdCentroCusto = s.IdCentroCusto,
            //                           ValorLancamento = totalDriver == 0 ? 0 : s.ValorLancamento * ((prod.DriverGGF == null ? 0 : prod.DriverGGF) / totalDriver),
            //                           DescricaoLancamento = "Rateio GGF - " + s.DescricaoLancamento,
            //                           IdPeriodo = s.IdPeriodo,
            //                           DataLancamento = System.DateTime.Now,
            //                           IdContaContabil = ContasContabeis[("9994Other costs (Undefined)").ToUpper()].IdContaContabil
            //                       }).ToList();


            //            foreach (var lanc in Rateios)
            //            {
            //                if (lanc.ValorLancamento != 0)
            //                {
            //                    lancHist.Add(new TB_LANCAMENTO_CUSTO_HISTORICO()
            //                    {
            //                        VALOR_LANCAMENTO = Math.Round((decimal)(lanc.ValorLancamento == null ? 0 : lanc.ValorLancamento), 2),
            //                        ID_PERIODO = (int)lanc.IdPeriodo,
            //                        ID_INDICADOR_CUSTO = Convert.ToInt32(IndicadoresCustos[Indicadores.IndicadoresCustos.OtherCostsUndefined].IdIndicadorCusto),
            //                        ID_PRODUTO = prod.IdProdutoPai == null ? prod.IdProduto : (int)prod.IdProdutoPai
            //                    });

            //                    contadorSaves++;
            //                    if (contadorSaves == 2500)
            //                    {
            //                        contadorSaves = 0;
            //                        lancHist.Save();
            //                        GC.Collect();
            //                    }
            //                }
            //            }
            //        }
            //    }

            //    ValoresDespGGF = null;

            //    OnImportData(this, new ImportDataEventArgs("Salvando valores GGF..."));
            //    Save();
            //    OnImportData(this, new ImportDataEventArgs("Salvando valores GGF (Custo)..."));
            //    LancamentoCusto.Save();
            //    OnImportData(this, new ImportDataEventArgs("Salvando valores GGF (Histórico)..."));
            //    lancHist.Save();
            //    OnImportData(this, new ImportDataEventArgs("Processando valores GGF (Giro de estoque)..."));
            //    GC.Collect();
            //    Custo cust = new Custo();
            //    cust.CalcularGiroEstoque(pMes, pAno, (int)IndicadoresCustos[Indicadores.IndicadoresCustos.OtherCostsUndefined].IdIndicadorCusto, Indicadores.IndicadoresCustos.OtherCostsUndefined, ContasContabeis[("9994Other costs (Undefined)").ToUpper()].IdContaContabil);


            //    SPExcluirLancamentosProdutosExportacao ExcluirProdutos = new SPExcluirLancamentosProdutosExportacao();
            //    ExcluirProdutos.Execute(pIdPeriodo, (int)IndicadoresCustos[Indicadores.IndicadoresCustos.ImportDuties].IdIndicadorCusto);

            //    GC.Collect();
            //}
            //catch (Exception ex)
            //{
            //    Exportacao.Texto.LogErro(ex, "Rateio GGF");
            //    throw new Exception(ex.Message);
            //}

            #endregion Rateio GGF

            GC.Collect();

            #region Coment2
            //#region Rateio Vendas
            //try
            //{
            //    OnImportData(this, new ImportDataEventArgs("Cálculo de rateio de Vendas..."));
            //    centros = (from s in CentroCusto.GetLista()
            //               join t in TiposRateios
            //               on s.IdCentroCusto equals t.IdCentroCusto
            //               where t.IdDriverRateioTipo == DriversRateiosTipos["Rateio Vendas Real"].IdDriverRateioTipo
            //               select new CentroCusto.Lista
            //               {
            //                   IdCentroCusto = s.IdCentroCusto,
            //                   IdIndicadorDespesa = s.IdIndicadorDespesa,
            //                   IdDriverRateioTipo = t.IdDriverRateioTipo,
            //                   Produtos = CentroCusto.GetProdutos(s.IdCentroCusto, pIdPeriodo)
            //               }).ToList();

            //    var TotalDriverNetNet = (from s in ListaProdutoDriverRateioValor
            //                             select new ProdutoDriverRateioValor.Lista()
            //                             {
            //                                 ValorNetNet = s.ValorNetNet,
            //                                 IdProduto = s.IdProduto
            //                             }).ToList();
            //    i = 0;
            //    contadorSaves = 0;
            //    foreach (var cent in centros)
            //    {
            //        i++;
            //        OnImportData(this, new ImportDataEventArgs("Calculando Rateio de Vendas...", i, centros.Count()));

            //        TotalDriverFamilia = (from s in TotalDriverNetNet
            //                              join p in cent.Produtos
            //                              on s.IdProduto equals p.IdProduto
            //                              select s.ValorNetNet).Sum();

            //        foreach (var prod in cent.Produtos)
            //        {

            //            //GC.Collect();

            //            Rateios = (from s in Valores.Where(w => w.IdCentroCusto == cent.IdCentroCusto).Select(s => s)
            //                       select new Lista
            //                       {
            //                           IdCentroCusto = s.IdCentroCusto,
            //                           ValorLancamento = TotalDriverFamilia == 0 ? 0 : s.ValorLancamento * ((prod.DriverNetNet == null ? 0 : prod.DriverNetNet) / TotalDriverFamilia),
            //                           DescricaoLancamento = "Rateio Vendas - " + s.DescricaoLancamento,
            //                           IdPeriodo = s.IdPeriodo,
            //                           DataLancamento = System.DateTime.Now,
            //                           IdContaContabil = ContasContabeis.ContainsKey(s.CodigoCentroCusto + s.NomeCentroCusto.ToUpper()) ? (int?)ContasContabeis[s.CodigoCentroCusto + s.NomeCentroCusto.ToUpper()].IdContaContabil : null,
            //                           IdIndicadorDespesa = cent.IdIndicadorDespesa
            //                       }).ToList();

            //            foreach (var item in Rateios)
            //            {
            //                if (item.ValorLancamento != 0)
            //                {
            //                    Add(new TB_LANCAMENTO()
            //                    {
            //                        ID_CENTRO_CUSTO = item.IdCentroCusto,
            //                        VALOR_LANCAMENTO = Math.Round((decimal)(item.ValorLancamento == null ? 0 : item.ValorLancamento), 2),
            //                        DESCRICAO_LANCAMENTO = item.DescricaoLancamento,
            //                        ID_PERIODO = item.IdPeriodo,
            //                        DATA_LANCAMENTO = item.DataLancamento,
            //                        ID_CONTA_CONTABIL = item.IdContaContabil,
            //                        ID_LANCAMENTO_TIPO = LancamentosTipos["Real"].IdLancamentoTipo,
            //                        TB_LANCAMENTO_DESPESA = new TrackableCollection<TB_LANCAMENTO_DESPESA>()
            //                        {
            //                            new TB_LANCAMENTO_DESPESA()
            //                            {
            //                                 ID_INDICADOR_DESPESA = (int)item.IdIndicadorDespesa,
            //                                 ID_PRODUTO = prod.IdProduto
            //                            }
            //                        }
            //                    });
            //                }
            //                contadorSaves++;
            //                if (contadorSaves == 2500)
            //                {
            //                    contadorSaves = 0;
            //                    Save();
            //                    lancamentoDespesa.Save();
            //                    GC.Collect();
            //                }
            //            }
            //        }
            //        //OnImportData(this, new ImportDataEventArgs(String.Format("Salvando informações... - {0} de {1}", i, centros.Count())));
            //        Save();
            //        lancamentoDespesa.Save();
            //    }


            //    //GC.Collect();

            //}
            //catch (Exception ex)
            //{
            //    Exportacao.Texto.LogErro(ex, "Rateio Vendas");
            //    throw new Exception(ex.Message);
            //}

            //#endregion Rateio Vendas

            //GC.Collect();

            //#region Rateio Promoção de grade

            //try
            //{
            //    OnImportData(this, new ImportDataEventArgs("Cálculo de rateio de Promoção de Grade..."));
            //    centros = (from s in CentroCusto.GetLista()
            //               join t in TiposRateios
            //               on s.IdCentroCusto equals t.IdCentroCusto
            //               where t.IdDriverRateioTipo == DriversRateiosTipos["Rateio PromocaoGrade Real"].IdDriverRateioTipo
            //               select new CentroCusto.Lista
            //               {
            //                   IdCentroCusto = s.IdCentroCusto,
            //                   IdIndicadorDespesa = s.IdIndicadorDespesa,
            //                   IdDriverRateioTipo = t.IdDriverRateioTipo,
            //                   Produtos = CentroCusto.GetProdutos(s.IdCentroCusto, pIdPeriodo)
            //               }).ToList();


            //    lancamentoDespesa = new LancamentoDespesa();

            //    i = 0;
            //    contadorSaves = 0;
            //    foreach (var cent in centros)
            //    {
            //        i++;
            //        OnImportData(this, new ImportDataEventArgs("Calculando Rateio de Promoção de Grade...", i, centros.Count()));



            //        foreach (var prod in cent.Produtos)
            //        {
            //            Produto produto = new Produto();

            //            var familiaProdutos = (from s in produto.GetLista(new Produto.Lista() { IdProdutoFamilia = prod.IdProdutoFamilia })
            //                                   select new Produto.Lista()
            //                                   {
            //                                       IdProduto = s.IdProduto
            //                                   }
            //                                   ).ToList();

            //            var totalDriver = (from s in ListaProdutoDriverRateioValor
            //                               join p in familiaProdutos
            //                               on s.IdProduto equals p.IdProduto
            //                               select s.ValorNetNet).Sum();


            //            Rateios = (from s in Valores.Where(w => w.IdCentroCusto == cent.IdCentroCusto).Select(s => s)
            //                       select new Lista
            //                       {
            //                           IdCentroCusto = s.IdCentroCusto,
            //                           ValorLancamento = totalDriver == 0 ? 0 : ((s.ValorLancamento * prod.DriverGradePromocional) / 100) * ((prod.DriverNetNet == null ? 0 : prod.DriverNetNet) / totalDriver),
            //                           DescricaoLancamento = "Rateio Grade - " + s.DescricaoLancamento,
            //                           IdPeriodo = s.IdPeriodo,
            //                           DataLancamento = System.DateTime.Now,
            //                           //IdContaContabil = s.IdContaContabil,
            //                           IdContaContabil = ContasContabeis.ContainsKey(s.CodigoCentroCusto + s.NomeCentroCusto.ToUpper()) ? (int?)ContasContabeis[s.CodigoCentroCusto + s.NomeCentroCusto.ToUpper()].IdContaContabil : null,
            //                           IdIndicadorDespesa = cent.IdIndicadorDespesa
            //                       }).ToList();

            //            foreach (var lanc in Rateios)
            //            {
            //                if (lanc.ValorLancamento != 0)
            //                {
            //                    Add(new TB_LANCAMENTO()
            //                    {
            //                        ID_CENTRO_CUSTO = lanc.IdCentroCusto,
            //                        VALOR_LANCAMENTO = Math.Round((decimal)(lanc.ValorLancamento == null ? 0 : lanc.ValorLancamento), 2),
            //                        DESCRICAO_LANCAMENTO = lanc.DescricaoLancamento,
            //                        ID_PERIODO = lanc.IdPeriodo,
            //                        DATA_LANCAMENTO = lanc.DataLancamento,
            //                        ID_CONTA_CONTABIL = lanc.IdContaContabil,
            //                        ID_LANCAMENTO_TIPO = LancamentosTipos["Real"].IdLancamentoTipo,
            //                        TB_LANCAMENTO_DESPESA = new TrackableCollection<TB_LANCAMENTO_DESPESA>()
            //                        {
            //                            new TB_LANCAMENTO_DESPESA()
            //                            {
            //                                 ID_INDICADOR_DESPESA = (int)lanc.IdIndicadorDespesa,
            //                                 ID_PRODUTO = prod.IdProduto
            //                            }
            //                        }
            //                    });
            //                }
            //                contadorSaves++;
            //                if (contadorSaves == 2500)
            //                {
            //                    contadorSaves = 0;
            //                    Save();
            //                    lancamentoDespesa.Save();
            //                    GC.Collect();
            //                }
            //            }
            //        }
            //        //OnImportData(this, new ImportDataEventArgs(String.Format("Salvando informações... - {0} de {1}", i, centros.Count())));
            //        Save();
            //        lancamentoDespesa.Save();

            //    }


            //}
            //catch (Exception ex)
            //{
            //    Exportacao.Texto.LogErro(ex, "Rateio Promoção de grade");
            //    throw new Exception(ex.Message);
            //}

            //#endregion

            //OnImportData(this, new ImportDataEventArgs("Salvando informações no banco..."));
            #endregion



            //Save();
            //LancamentoVenda.Save();
            //LancamentoCusto.Save();
            //LancamentoDespesa.Save();

            GC.RemoveMemoryPressure(Int32.MaxValue);
            OnImportData(this, new ImportDataEventArgs("Cálculos de Rateio efetuados com sucesso!"));
        }

        private void AtualizaIndicadorNetNetSales(int pIdPeriodo)
        {

            // Dictionary de Contas Contábeis para recuperar o ID, utilizando a descrição
            ContaContabil ContaContabil = new ContaContabil();
            var ContasContabeis = ContaContabil.GetItens(new ContaContabil.Lista() { IndicaGerencial = true }).ToDictionary(d => d.CodigoContaContabil + d.DescricaoContaContabil.ToUpper());
            ContaContabil = null;

            // Dictionary de Indicadores de Vendas para recuperar o ID, utilizando o nome
            IndicadorVenda IndicadorVenda = new IndicadorVenda();
            var IndicadoresVendas = IndicadorVenda.GetLista().ToDictionary(d => d.NomeIndicadorVenda);
            IndicadorVenda = null;

            // Dictionary de Indicadores de Custos para recuperar o ID, utilizando o nome
            IndicadorCusto IndicadorCusto = new IndicadorCusto();
            var IndicadoresCustos = IndicadorCusto.GetLista().ToDictionary(d => d.NomeIndicadorCusto);
            IndicadorCusto = null;

            // Dictionary de Indicadores de Despesas para recuperar o ID, utilizando o nome
            IndicadorDespesa IndicadorDespesa = new IndicadorDespesa();
            var IndicadoresDespesas = IndicadorDespesa.GetLista().ToDictionary(d => d.NomeIndicadorDespesa);
            IndicadorDespesa = null;

            // Dictionary de Tipos de Lançamentos para recuperar o ID, utilizando a descrição
            LancamentoTipo LancamentoTipo = new LancamentoTipo();
            var LancamentosTipos = LancamentoTipo.GetLista().ToDictionary(d => d.DescricaoLancamentoTipo);
            LancamentoTipo = null;

            // Busca os valores de venda pelo período informado
            LancamentoVenda LancamentoVenda = new LancamentoVenda();
            List<Lista> ValoresNetSales = (from s in GetLista(new Lista() { IdPeriodo = pIdPeriodo, DescricaoLancamentoTipo = "Real" })
                                           join d in LancamentoVenda.GetLista()
                                           on s.IdLancamento equals d.IdLancamento
                                           where (d.IdIndicadorVenda == IndicadoresVendas[Indicadores.IndicadoresVendas.NetSales].IdIndicadorVenda)
                                           select s).GroupBy(g => new
                                           {
                                               IdProdutoVenda = g.IdProdutoVenda
                                           }).Select(s => new Lista()
                                           {
                                               IdProdutoVenda = s.Key.IdProdutoVenda,
                                               ValorLancamento = s.Sum(su => su.ValorLancamento),
                                               DescricaoLancamento = "",
                                               IdPeriodo = pIdPeriodo,
                                               DataLancamento = DateTime.Now,
                                               IdContaContabil = ContasContabeis[("9888Net Net Sales").ToUpper()].IdContaContabil, //114 // TODO: 
                                           }).ToList();

            List<Lista> ValoresTradeAllowance = (from s in GetLista(new Lista() { IdPeriodo = pIdPeriodo, DescricaoLancamentoTipo = "Real" })
                                                 join d in LancamentoVenda.GetLista()
                                                 on s.IdLancamento equals d.IdLancamento
                                                 where (d.IdIndicadorVenda == IndicadoresVendas[Indicadores.IndicadoresVendas.TradeAllowances].IdIndicadorVenda)
                                                 select s).GroupBy(g => new
                                                 {
                                                     IdProdutoVenda = g.IdProdutoVenda
                                                 }).Select(s => new Lista()
                                                 {
                                                     IdProdutoVenda = s.Key.IdProdutoVenda,
                                                     ValorLancamento = s.Sum(su => su.ValorLancamento),
                                                     DescricaoLancamento = "Indicador Net Net Sales",
                                                     IdPeriodo = pIdPeriodo,
                                                     DataLancamento = DateTime.Now,
                                                     IdContaContabil = ContasContabeis[("9888Net Net Sales").ToUpper()].IdContaContabil, //114 // TODO: 
                                                 }).ToList();

            var Valores = (from n in ValoresNetSales
                           join t in ValoresTradeAllowance
                           on n.IdProdutoVenda equals t.IdProdutoVenda
                           into v
                           from t in v.DefaultIfEmpty()
                           select new Lista()
                           {
                               IdProdutoVenda = n.IdProdutoVenda,
                               ValorLancamento = (n == null ? 0 : n.ValorLancamento) - (t == null ? 0 : t.ValorLancamento),
                               DescricaoLancamento = "Indicador Net Net Sales",
                               IdPeriodo = pIdPeriodo,
                               DataLancamento = DateTime.Now,
                               IdContaContabil = ContasContabeis[("9888Net Net Sales").ToUpper()].IdContaContabil,
                           }).ToList();

            foreach (var lanc in Valores)
            {
                Add(new TB_LANCAMENTO()
                {
                    VALOR_LANCAMENTO = lanc.ValorLancamento,
                    DESCRICAO_LANCAMENTO = lanc.DescricaoLancamento,
                    ID_PERIODO = lanc.IdPeriodo,
                    DATA_LANCAMENTO = lanc.DataLancamento,
                    ID_CONTA_CONTABIL = lanc.IdContaContabil,
                    ID_LANCAMENTO_TIPO = LancamentosTipos["Real"].IdLancamentoTipo,
                    TB_LANCAMENTO_VENDA = new TrackableCollection<TB_LANCAMENTO_VENDA>()
                            {
                                new TB_LANCAMENTO_VENDA()
                                {
                                     ID_INDICADOR_VENDA = IndicadoresVendas[Indicadores.IndicadoresVendas.NetNetSales].IdIndicadorVenda,
                                     ID_PRODUTO = (int)lanc.IdProdutoVenda,
                                     INDICA_PROVISAO = false
                                }
                            }
                });
            }
            Save();
            LancamentoVenda.Save();
            GC.Collect();
        }

        private void AtualizaValorDriverVenda(int pIdPeriodo)
        {

            // Dictionary de Contas Contábeis para recuperar o ID, utilizando a descrição
            ContaContabil ContaContabil = new ContaContabil();
            var ContasContabeis = ContaContabil.GetItens(new ContaContabil.Lista() { IndicaGerencial = true }).ToDictionary(d => d.CodigoContaContabil + d.DescricaoContaContabil.ToUpper());
            ContaContabil = null;

            // Dictionary de Indicadores de Vendas para recuperar o ID, utilizando o nome
            IndicadorVenda IndicadorVendas = new IndicadorVenda();
            var IndicadoresVenda = IndicadorVendas.GetLista().ToDictionary(d => d.NomeIndicadorVenda);
            IndicadorVendas = null;

            // Dictionary de Indicadores de Custos para recuperar o ID, utilizando o nome
            IndicadorCusto IndicadorCusto = new IndicadorCusto();
            var IndicadoresCusto = IndicadorCusto.GetLista().ToDictionary(d => d.NomeIndicadorCusto);
            IndicadorCusto = null;

            // Dictionary de Indicadores de Despesas para recuperar o ID, utilizando o nome
            IndicadorDespesa IndicadorDespesa = new IndicadorDespesa();
            var IndicadoresDespesa = IndicadorDespesa.GetLista().ToDictionary(d => d.NomeIndicadorDespesa);
            IndicadorDespesa = null;

            // Busca os valores de venda pelo período informado
            LancamentoVenda vendas = new LancamentoVenda();

            List<Lista> valores = (from s in GetLista(new Lista() { IdPeriodo = pIdPeriodo, DescricaoLancamentoTipo = "Real" })
                                   join d in vendas.GetLista(new LancamentoVenda.Lista() { IdIndicadorVenda = IndicadoresVenda[Indicadores.IndicadoresVendas.NetSales].IdIndicadorVenda })
                                           on s.IdLancamento equals d.IdLancamento
                                   select s).GroupBy(g => new
                                   {
                                       IdProdutoVenda = g.IdProdutoVenda
                                   }).Select(s => new Lista()
                                   {
                                       IdProdutoVenda = s.Key.IdProdutoVenda,
                                       ValorLancamento = s.Sum(su => su.ValorLancamento)

                                   }).ToList();

            // Busca os produtos
            Produto produto = new Produto();
            List<Produto.Lista> produtos = (from s in produto.GetLista()
                                            select s).ToList();
            produto = null;

            // Agrupa os valores encontrados pelos produtos, gerando os valores dos drivers
            //var iValoresTotaisCC = (from s in valores
            //                        group s by new Lista
            //                        {
            //                            IdProdutoVenda = s.IdProdutoVenda
            //                        } into gr
            //                        join p in produtos
            //                        on gr.Key.IdProdutoVenda equals p.IdProduto
            //                        select new Lista
            //                        {
            //                            IdProdutoVenda = p.IdProduto,
            //                            ValorLancamento = gr.Sum(s => s.ValorLancamento)
            //                        });

            // Monta a lista para atualização de acordo com os valores encontrados
            List<ProdutoDriverRateioValor.Lista> valoresDriversCalculo = (from s in valores
                                                                          select new ProdutoDriverRateioValor.Lista()
                                                                          {
                                                                              IdPeriodo = pIdPeriodo,
                                                                              IdProduto = Convert.ToInt32(s.IdProdutoVenda),
                                                                              ValorVenda = s.ValorLancamento
                                                                          }).ToList();

            // Busca Valores de Driver existentes
            ProdutoDriverRateioValor driver = new ProdutoDriverRateioValor();
            List<ProdutoDriverRateioValor.Lista> valoresDriversSQL = (from s in driver.GetLista(new ProdutoDriverRateioValor.Lista() { IdPeriodo = pIdPeriodo })
                                                                      select new ProdutoDriverRateioValor.Lista()
                                                                      {
                                                                          IdProdutoDriverRateioValor = s.IdProdutoDriverRateioValor,
                                                                          IdPeriodo = pIdPeriodo,
                                                                          IdProduto = s.IdProduto,
                                                                          ValorVenda = s.ValorVenda,
                                                                          ValorGGF = s.ValorGGF,
                                                                          ValorNetNet = s.ValorNetNet
                                                                      }).ToList();

            // Compara o resultado do cálculo com o resultado da busca no banco
            var novos = (from c in valoresDriversCalculo
                         join db in valoresDriversSQL
                         on c.IdProduto equals db.IdProduto
                         into driverVenda
                         from db in driverVenda.DefaultIfEmpty()
                         where db == null
                         select new ProdutoDriverRateioValor.Lista()
                         {
                             IdPeriodo = pIdPeriodo,
                             IdProduto = c.IdProduto,
                             ValorVenda = c.ValorVenda
                         }).ToList();


            // Insere as novas ocorrências
            int i = 0;
            OnImportData(this, new ImportDataEventArgs("Incluindo valores de Drivers de Venda..."));
            if (novos != null && novos.Count() > 0)
            {
                foreach (var item in novos)
                {
                    driver.Add(new TB_PRODUTO_DRIVER_RATEIO_VALOR() { ID_PRODUTO = item.IdProduto, VALOR_VENDA = item.ValorVenda, ID_PERIODO = (int)item.IdPeriodo });
                    i++;
                    OnImportData(this, new ImportDataEventArgs("Incluindo valores de Drivers de Venda...", i, novos.Count()));
                }
            }

            // Localiza os registros a serem alterados 
            List<ProdutoDriverRateioValor.Lista> alterados = (from c in valoresDriversCalculo
                                                              join db in valoresDriversSQL
                                                              on c.IdProduto equals db.IdProduto
                                                              where c.ValorVenda != db.ValorVenda
                                                              select new ProdutoDriverRateioValor.Lista()
                                                              {
                                                                  IdProdutoDriverRateioValor = db.IdProdutoDriverRateioValor,
                                                                  IdPeriodo = pIdPeriodo,
                                                                  IdProduto = c.IdProduto,
                                                                  ValorVenda = c.ValorVenda,
                                                                  ValorGGF = db.ValorGGF,
                                                                  ValorNetNet = db.ValorNetNet
                                                              }).ToList();


            // Altera os registros encontrados no banco
            i = 0;
            OnImportData(this, new ImportDataEventArgs("Editando valores de Drivers de Venda..."));
            if (alterados != null && alterados.Count() > 0)
            {
                foreach (var item in alterados)
                {
                    driver.Update(new TB_PRODUTO_DRIVER_RATEIO_VALOR()
                    {
                        ID_PRODUTO = item.IdProduto,
                        ID_PRODUTO_DRIVER_RATEIO_VALOR = item.IdProdutoDriverRateioValor,
                        ID_PERIODO = (int)item.IdPeriodo,
                        VALOR_GGF = item.ValorGGF,
                        VALOR_NET_NET = item.ValorNetNet,
                        VALOR_VENDA = item.ValorVenda
                    });
                    i++;
                    OnImportData(this, new ImportDataEventArgs("Alterando valores de Drivers de Venda...", i, alterados.Count()));
                }
            }


            if (novos != null && novos.Count() == 0 && alterados != null && alterados.Count() == 0)
                OnImportData(this, new ImportDataEventArgs("Os valores de driver de venda para o período selecionado já estão preenchidos. Não foram realizadas alterações."));
            else
                OnImportData(this, new ImportDataEventArgs("Atualização efetuada com sucesso."));

            GC.Collect();
        }

        private void AtualizaValorDriverNetNet(int pIdPeriodo)
        {

            // Dictionary de Contas Contábeis para recuperar o ID, utilizando a descrição
            ContaContabil ContaContabil = new ContaContabil();
            var ContasContabeis = ContaContabil.GetItens(new ContaContabil.Lista() { IndicaGerencial = true }).ToDictionary(d => d.CodigoContaContabil + d.DescricaoContaContabil.ToUpper());
            ContaContabil = null;

            // Dictionary de Indicadores de Vendas para recuperar o ID, utilizando o nome
            IndicadorVenda IndicadorVendas = new IndicadorVenda();
            var IndicadoresVenda = IndicadorVendas.GetLista().ToDictionary(d => d.NomeIndicadorVenda);
            IndicadorVendas = null;

            // Dictionary de Indicadores de Custos para recuperar o ID, utilizando o nome
            IndicadorCusto IndicadorCusto = new IndicadorCusto();
            var IndicadoresCusto = IndicadorCusto.GetLista().ToDictionary(d => d.NomeIndicadorCusto);
            IndicadorCusto = null;

            // Dictionary de Indicadores de Despesas para recuperar o ID, utilizando o nome
            IndicadorDespesa IndicadorDespesa = new IndicadorDespesa();
            var IndicadoresDespesa = IndicadorDespesa.GetLista().ToDictionary(d => d.NomeIndicadorDespesa);
            IndicadorDespesa = null;

            // Busca os valores de venda pelo período informado
            LancamentoVenda vendas = new LancamentoVenda();
            //List<Lista> valores = (from s in GetLista(new Lista() { IdPeriodo = pIdPeriodo, DescricaoLancamentoTipo = "Real" })
            //                       join d in vendas.GetLista(new LancamentoVenda.Lista() { IdIndicadorVenda = IndicadoresVenda[Indicadores.IndicadoresVendas.NetSales].IdIndicadorVenda })
            //                       on s.IdLancamento equals d.IdLancamento
            //                       select s).ToList();

            List<Lista> valores = (from s in GetLista(new Lista() { IdPeriodo = pIdPeriodo, DescricaoLancamentoTipo = "Real" })
                                   join d in vendas.GetLista(new LancamentoVenda.Lista() { IdIndicadorVenda = IndicadoresVenda[Indicadores.IndicadoresVendas.NetNetSales].IdIndicadorVenda })
                                           on s.IdLancamento equals d.IdLancamento
                                   select s).GroupBy(g => new
                                   {
                                       IdProdutoVenda = g.IdProdutoVenda
                                   }).Select(s => new Lista()
                                   {
                                       IdProdutoVenda = s.Key.IdProdutoVenda,
                                       ValorLancamento = s.Sum(su => su.ValorLancamento)

                                   }).ToList();


            // Busca os produtos
            Produto produto = new Produto();
            List<Produto.Lista> produtos = (from s in produto.GetLista()
                                            select s).ToList();

            // Agrupa os valores encontrados pelos produtos, gerando os valores dos drivers
            //var iValoresTotaisCC = (from s in valores.GroupBy(g => g.IdProdutoVenda).
            //                        Select(s => new Lista
            //                        {
            //                            IdProdutoVenda = s.Key,
            //                            ValorLancamento = s.Sum(sl => sl.ValorLancamento)
            //                        })
            //                        join p in produtos
            //                        on s.IdProdutoVenda equals p.IdProduto
            //                        select new Lista
            //                        {
            //                            IdProdutoVenda = s.IdProdutoVenda,
            //                            ValorLancamento = s.ValorLancamento
            //                        });

            // Monta a lista para atualização de acordo com os valores encontrados
            List<ProdutoDriverRateioValor.Lista> valoresDriversCalculo = (from s in valores
                                                                          select new ProdutoDriverRateioValor.Lista()
                                                                          {
                                                                              IdPeriodo = pIdPeriodo,
                                                                              IdProduto = (int)s.IdProdutoVenda,
                                                                              ValorNetNet = s.ValorLancamento
                                                                          }).ToList();

            // Busca Valores de Driver existentes
            ProdutoDriverRateioValor driver = new ProdutoDriverRateioValor();
            List<ProdutoDriverRateioValor.Lista> valoresDriversSQL = (from s in driver.GetLista(new ProdutoDriverRateioValor.Lista() { IdPeriodo = pIdPeriodo })
                                                                      select new ProdutoDriverRateioValor.Lista()
                                                                      {
                                                                          IdProdutoDriverRateioValor = s.IdProdutoDriverRateioValor,
                                                                          IdPeriodo = pIdPeriodo,
                                                                          IdProduto = s.IdProduto,
                                                                          ValorNetNet = s.ValorNetNet,
                                                                          ValorGGF = s.ValorGGF,
                                                                          ValorVenda = s.ValorVenda
                                                                      }).ToList();

            // Compara o resultado do cálculo com o resultado da busca no banco
            var novos = (from c in valoresDriversCalculo
                         join db in valoresDriversSQL
                         on c.IdProduto equals db.IdProduto
                         into driverVenda
                         from db in driverVenda.DefaultIfEmpty()
                         where db == null
                         select new ProdutoDriverRateioValor.Lista()
                         {
                             IdPeriodo = pIdPeriodo,
                             IdProduto = c.IdProduto,
                             ValorNetNet = c.ValorNetNet
                         }).ToList();


            // Insere as novas ocorrências
            int i = 0;
            OnImportData(this, new ImportDataEventArgs("Incluindo valores de Drivers de Venda Net Net..."));
            if (novos != null && novos.Count() > 0)
            {
                foreach (var item in novos)
                {
                    driver.Add(new TB_PRODUTO_DRIVER_RATEIO_VALOR() { ID_PRODUTO = item.IdProduto, VALOR_NET_NET = item.ValorNetNet, ID_PERIODO = (int)item.IdPeriodo });
                    i++;
                    OnImportData(this, new ImportDataEventArgs("Incluindo valores de Drivers de Venda Net Net...", i, novos.Count()));
                }
            }

            // Localiza os registros a serem alterados 
            List<ProdutoDriverRateioValor.Lista> alterados = (from c in valoresDriversCalculo
                                                              join db in valoresDriversSQL
                                                              on c.IdProduto equals db.IdProduto
                                                              where Math.Round((decimal)(c.ValorVenda == null ? 0 : c.ValorVenda), 2) != Math.Round((decimal)(db.ValorVenda == null ? 0 : db.ValorVenda), 2)
                                                              select new ProdutoDriverRateioValor.Lista()
                                                              {
                                                                  IdProdutoDriverRateioValor = db.IdProdutoDriverRateioValor,
                                                                  IdPeriodo = pIdPeriodo,
                                                                  IdProduto = c.IdProduto,
                                                                  ValorVenda = db.ValorVenda,
                                                                  ValorGGF = db.ValorGGF,
                                                                  ValorNetNet = c.ValorNetNet
                                                              }).ToList();


            // Altera os registros encontrados no banco
            i = 0;
            OnImportData(this, new ImportDataEventArgs("Alterando valores de Drivers de Venda Net Net..."));
            if (alterados != null && alterados.Count() > 0)
            {
                foreach (var item in alterados)
                {
                    driver.Update(new TB_PRODUTO_DRIVER_RATEIO_VALOR()
                    {
                        ID_PRODUTO = item.IdProduto,
                        ID_PRODUTO_DRIVER_RATEIO_VALOR = item.IdProdutoDriverRateioValor,
                        ID_PERIODO = (int)item.IdPeriodo,
                        VALOR_GGF = item.ValorGGF,
                        VALOR_NET_NET = item.ValorNetNet,
                        VALOR_VENDA = item.ValorVenda
                    });
                    i++;
                    OnImportData(this, new ImportDataEventArgs("Alterando valores de Drivers de Venda Net Net...", i, alterados.Count()));
                }
            }


            if (novos != null && novos.Count() == 0 && alterados != null && alterados.Count() == 0)
                OnImportData(this, new ImportDataEventArgs("Os valores de driver de venda net net para o período selecionado já estão preenchidos. Não foram realizadas alterações."));
            else
                OnImportData(this, new ImportDataEventArgs("Atualização efetuada com sucesso."));
            GC.Collect();
        }

        #endregion Rateios

        #endregion Processos

        #region Classes

        /// <summary>
        /// Lista com as propriedades da classe
        /// </summary>
        public class Lista
        {
            public int IdLancamento { get; set; }
            public int IdLancamentoDespesa { get; set; }
            public int IdLancamentoVenda { get; set; }
            public int IdLancamentoCusto { get; set; }
            public int? IdCentroCusto { get; set; }
            public int? IdCentroCustoGerencial { get; set; }
            public string CodigoCentroCusto { get; set; }
            public string NomeCentroCusto { get; set; }
            public string CategoriaCentroCusto { get; set; }
            public bool? IndicaGerencial { get; set; }
            public bool? IndicaCorporativo { get; set; }
            public bool? IndicaAlocacao { get; set; }
            public int? IdContaContabil { get; set; }
            public string CodigoContaContabil { get; set; }
            public string DescricaoContaContabil { get; set; }
            public int? IdLancamentoTipo { get; set; }
            public int? IdProjeto { get; set; }
            public DateTime? DataLancamento { get; set; }
            public decimal? ValorLancamento { get; set; }
            public DateTime? DataEntradaSun { get; set; }
            public int? IdPeriodo { get; set; }
            public DateTime? DataInclusao { get; set; }
            public string DescricaoLancamento { get; set; }
            public int? IdEvento { get; set; }
            public int? IdFuncionario { get; set; }
            public int? IdMapaEstrategicoItem { get; set; }
            public bool? IndicaDespesaComprometida { get; set; }
            public string ContratoDespesaComprometida { get; set; }
            public int? IdIndicadorDespesa { get; set; }
            public string DescricaoLancamentoTipo { get; set; }
            public int? IdProdutoVenda { get; set; }
            public bool? IndicaIndicadorDespesa { get; set; }
            public bool? IndicaTradeAllowance { get; set; }
        }

        #endregion Classes

        public event ImportDataEventHandler OnImportData;
    }

    public class LancamentoBLO<T> where T : TB_LANCAMENTO
    {
        /// <summary>
        /// LancamentoDAO
        /// </summary>
        private LancamentoDAO<T> _base = new LancamentoDAO<T>();

        /// <summary>
        /// Adiciona uma entidade no sistema
        /// </summary>
        /// <param name="pEntity">pEntity</param>
        /// <returns>Entidade</returns>
        public void Add(T pEntity)
        {
            Validate(pEntity);
            _base.Add(pEntity);
            //return _base.Save(pEntity);
        }

        /// <summary>
        /// Salva uma entidade do sistema
        /// </summary>
        /// <param name="pEntity">pEntity</param>
        /// <returns>Entidade</returns>
        public void Save()
        {
            _base.Save();
        }

        /// <summary>
        /// Deleta uma entidade do sistema
        /// </summary>
        /// <param name="pEntity">pEntity</param>
        public void Delete(T pEntity)
        {
            _base.Delete(pEntity);
            //_base.Save(pEntity);
        }

        /// <summary>
        /// Atualiza uma entidade do sistema
        /// </summary>
        /// <param name="pEntity">pEntity</param>
        /// <returns>Entidade</returns>
        public void Update(T pEntity)
        {
            Validate(pEntity);
            _base.Update(pEntity);
            //return _base.Save(pEntity);
        }

        /// <summary>
        /// Recupera uma entidade do sistema
        /// </summary>
        /// <returns>Lista</returns>
        public IQueryable<T> GetAll()
        {
            return _base.GetAll();
        }

        public IQueryable<TB_LANCAMENTO> GetAllDespesas()
        {
            return _base.GetAllDespesas();
        }

        public IQueryable<TB_LANCAMENTO> GetAllVendas()
        {
            return _base.GetAllVendas();
        }
        /// <summary>
        /// Valida a consistência da Entidade antes de 'comitar' a transação
        /// </summary>
        /// <param name="pEntity">Entidade</param>
        public void Validate(T pEntity)
        {

        }
    }
}